<template>
  <div class="tw-libsidenav">
    <div v-if="navTitleEnable && (parentNav.name || navTitle)"
      class="tw-libsidenav-header">
      <h4>{{parentNav.name || navTitle}}</h4>
    </div>

    <ul class="tw-libsidenav-body">
      <li class="tw-libsidenav-item"
        :class="{xactive:lv1Nav.active, xexpanded:lv1Nav.expanded}"
        v-for="(lv1Nav, lv1Idx) in navList"
        :key="lv1Idx">
        <a :href="lv1Nav.href + (dataIsFromPortal && lv1Nav.pageType !== '4' ? `?pageId=${lv1Nav.pageId}` : '')"
          :target="lv1Nav.target || '_self'"
          @click="clickNav(lv1Nav, $event)">
          <img class="xicon"
            v-if="getIcons('default', lv1Idx)"
            :src="`${$twApp.fileBaseUrl}${getIcons('default', lv1Idx)}`" />
          <img class="xhovericon"
            v-if="getIcons('hover', lv1Idx)"
            :src="`${$twApp.fileBaseUrl}${getIcons('hover', lv1Idx)}`" />
          <span>{{lv1Nav.name}}</span>
          <!-- 无子菜单时也显示右侧图标 -->
          <template v-if="ifShowSubNavIco && !lv1Nav.children">
            <img v-if="selfNavFold[0] && selfNavFold[0].localPath"
              class="tw-libsidenav-item-icon"
              :src="`${$twApp.fileBaseUrl}${selfNavFold[0].localPath}`" />
          </template>
          <!-- / 无子菜单时也显示右侧图标 -->
          <!--收起-->
          <template v-if="lv1Nav.children && !lv1Nav.expanded">
            <img v-if="selfNavMore && selfNavFold[0] && selfNavFold[0].localPath"
              class="tw-libsidenav-item-icon"
              :src="`${$twApp.fileBaseUrl}${selfNavFold[0].localPath}`" />
            <i v-else
              class="icon iconfont xcaret">&#xe671;</i>
          </template>
          <!--/收起-->

          <!--展开-->
          <template v-if="lv1Nav.children && lv1Nav.expanded">
            <img v-if="selfNavMore && selfNavUnFold[0] && selfNavUnFold[0].localPath"
              class="tw-libsidenav-item-icon"
              :src="`${$twApp.fileBaseUrl}${selfNavUnFold[0].localPath}`" />
            <i v-else
              class="icon iconfont xcaret">&#xe671;</i>
          </template>
          <!--展开-->
        </a>

        <ul v-if="lv1Nav.children && lv1Nav.expanded"
          class="tw-libsidenav-menus">
          <li class="tw-libsidenav-item xsub xlv2"
            :class="{xactive:lv2Nav.active, xexpanded:lv2Nav.expanded}"
            v-for="(lv2Nav, lv2Idx) in lv1Nav.children"
            :key="''+lv1Idx+lv2Idx">
            <a :style="{paddingLeft: computeNavIndentation(lv2Nav)}"
              :href="lv2Nav.href + (dataIsFromPortal && lv2Nav.pageType !== '4' ? `?pageId=${lv2Nav.pageId}&parentId=${lv1Nav.pageId}` : '')"
              :target="lv2Nav.target || '_self'"
              @click="clickNav(lv2Nav, $event)">
              <span>{{lv2Nav.name}}</span>
              <!--收起-->
              <template v-if="lv2Nav.children && !lv2Nav.expanded">
                <img v-if="selfNavMore && selfNavFold[0] && selfNavFold[0].localPath"
                  class="tw-libsidenav-item-icon"
                  :src="`${$twApp.fileBaseUrl}${selfNavFold[0].localPath}`" />
                <i v-else
                  class="icon iconfont xcaret">&#xe671;</i>
              </template>
              <!--/收起-->

              <!--展开-->
              <template v-if="lv2Nav.children && lv2Nav.expanded">
                <img v-if="selfNavMore && selfNavUnFold[0] && selfNavUnFold[0].localPath"
                  class="tw-libsidenav-item-icon"
                  :src="`${$twApp.fileBaseUrl}${selfNavUnFold[0].localPath}`" />
                <i v-else
                  class="icon iconfont xcaret">&#xe671;</i>
              </template>
              <!--展开-->
            </a>

            <ul v-if="lv2Nav.children && lv2Nav.expanded"
              class="tw-libsidenav-menus">
              <li class="tw-libsidenav-item xsub xlv3"
                :class="{xactive:lv3Nav.active}"
                v-for="(lv3Nav, lv3Idx) in lv2Nav.children"
                :key="''+lv1Idx+lv2Idx+lv3Idx">
                <a :style="{paddingLeft: computeNavIndentation(lv3Nav)}"
                  :href="lv3Nav.href + (dataIsFromPortal && lv3Nav.pageType !== '4' ? `?pageId=${lv3Nav.pageId}&parentId=${lv2Nav.pageId}&rootPageId=${lv1Nav.pageId}` : '')"
                  :target="lv3Nav.target || '_self'"
                  @click="clickNav(lv3Nav, $event)">
                  <span>{{lv3Nav.name}}</span>
                </a>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </div>
</template>

<script>
import props from './props'
import style from '../tw-lib-base/style'
import page from '../tw-lib-base/page/mixins'

export default {
  name: 'side-nav',

  mixins: [style, page],

  props,

  data () {
    return {
      navList: [],
      prevNav: null,
      activeNavId: null
    }
  },

  computed: {
    style () {
      return {
        hasNavShadow: this.hasNavShadow,
        navTitlePaddingX: this.navTitlePaddingX,
        hasNavTitltShadow: this.hasNavTitltShadow,
        navTitleAlign: this.navTitleAlign,
        navBoxBg: this.navBoxBg,
        navBoxRadius: this.navBoxRadius,
        navTitleHeight: this.navTitleHeight,
        navTitleBg: this.navTitleBg,
        navTitleBgColor1: this.navTitleBgColor1,
        navTitleBgColor2: this.navTitleBgColor2,
        navTitleGradientDeg: this.navTitleGradientDeg,
        navTitleSize: this.navTitleSize,
        navTitleColor: this.navTitleColor,
        navTitleIsBlod: this.navTitleIsBlod,
        navTitleHasBorder: this.navTitleHasBorder,
        navTitleBorderPosition: this.navTitleBorderPosition,
        navTitleBorderColor: this.navTitleBorderColor,
        navTitleBorderSize: this.navTitleBorderSize,
        navTitleBorderType: this.navTitleBorderType,
        navItemHeight: this.navItemHeight,
        navItemFontSize: this.navItemFontSize,
        navItemColor: this.navItemColor,
        navItemActiveBg: this.navItemActiveBg,
        navItemActiveColor: this.navItemActiveColor,
        iconMarginRight: this.iconMarginRight,
        navPaddingX: this.navPaddingX,
        navBodyPaddingY: this.navBodyPaddingY,
        subNavLineHeight: this.subNavLineHeight,
        subNavMaxHeight: this.subNavMaxHeight,
        subNavFontSize: this.subNavFontSize,
        subNavColor: this.subNavColor,
        navItemHasBorder: this.navItemHasBorder,
        navItemBorderPosition: this.navItemBorderPosition,
        navItemBorderColor: this.navItemBorderColor,
        navItemBorderSize: this.navItemBorderSize,
        navItemBorderType: this.navItemBorderType,
        itemWrap: this.itemWrap,
        selfNavMore: this.selfNavMore,
        selfNavFold: this.selfNavFold,
        selfNavUnFold: this.selfNavUnFold,
        ifShowSubNavIco: this.ifShowSubNavIco,
        navItemActiveIsBlod: this.navItemActiveIsBlod,
        navBgColor: this.navBgColor,
        navTitleImg: this.navTitleImg
      }
    }
  },

  methods: {
    getIcons (type, idx) {
      if (this.dataIsFromPortal) {
        if (type === 'default') {
          return this.navList[idx].defaultIcon
        } else {
          return this.navList[idx].hoverIcon || this.navList[idx].defaultIcon
        }
      } else {
        if (type === 'default') {
          return this.icons[idx] && this.icons[idx].localPath ? this.icons[idx].localPath : ''
        } else {
          return this.hoverIcons[idx] && this.hoverIcons[idx].localPath ? this.hoverIcons[idx].localPath : '' ||
            (this.icons[idx] && this.icons[idx].localPath ? this.icons[idx].localPath : '')
        }
      }
    },

    setStyle () {
      let style = `
        ::root.tw-libsidenav {
          background: ${this.navBoxBg};
          border-radius: ${this.navBoxRadius};
        }

        .tw-libsidenav-header {
          padding:0 ${this.navTitlePaddingX};
          height: ${this.navTitleHeight};
          line-height: ${this.navTitleHeight};
          text-align: ${this.navTitleAlign};
          background-color: ${this.navTitleBg};
          color: ${this.navTitleColor};
          border-top-left-radius: ${this.navBoxRadius};
          border-top-right-radius: ${this.navBoxRadius};
        }

        .tw-libsidenav-header > h4 {
          font-size: ${this.navTitleSize};
          font-weight: ${this.navTitleIsBlod ? '700' : '400'};
        }

        .tw-libsidenav > .tw-libsidenav-body {
          padding: ${this.navBodyPaddingY};
        }

        .tw-libsidenav-item {
          background-color: ${this.navBgColor};
          margin-bottom: ${this.navDistance};
        }

        .tw-libsidenav-item > a {
          padding: 0 ${this.navPaddingX};
          line-height: ${this.navItemHeight};
          font-size: ${this.navItemFontSize};
          color: ${this.navItemColor};
        }

        .tw-libsidenav-item.xsub > a {
          font-size: ${this.subNavFontSize};
          color: ${this.subNavColor};
        }

        .tw-libsidenav-item.xactive > a {
          background-color: ${this.navItemActiveBg};
        }

        .tw-libsidenav-item:hover > a,
        .tw-libsidenav-item.xactive > a,
        .tw-libsidenav-item.xexpanded > a {
          color: ${this.navItemActiveColor};
          font-weight: ${this.navItemActiveIsBlod ? '700' : '400'};
        }

        .tw-libsidenav-item > a > .xicon,
        .tw-libsidenav-item > a > .xhovericon {
          margin-right: ${this.iconMarginRight};
        }
      `

      if (this.navTitleBgColor1 && this.navTitleBgColor2) {
        style += `
          .tw-libsidenav-header {
            background-image: linear-gradient(${this.navTitleGradientDeg}deg, ${this.navTitleBgColor1}, ${this.navTitleBgColor2});
          }
        `
      }

      if (!this.itemWrap) {
        style += `
          ::root .tw-libsidenav-item > a {
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
          }
        `
      }

      if (this.navTitleHasBorder) {
        const border = `${this.navTitleBorderSize} ${this.navTitleBorderType} ${this.navTitleBorderColor}`
        if (this.navTitleBorderPosition.includes(0)) {
          style += `
              .tw-libsidenav-header {
                border-top: ${border};
              }
            `
        }

        if (this.navTitleBorderPosition.includes(1)) {
          style += `
              .tw-libsidenav-header {
                border-bottom: ${border};
              }
            `
        }

        if (this.navTitleBorderPosition.includes(2)) {
          style += `
              .tw-libsidenav-header {
                border-left: ${border};
              }
            `
        }

        if (this.navTitleBorderPosition.includes(3)) {
          style += `
              .tw-libsidenav-header {
                border-right: ${border};
              }
            `
        }
      }

      if (this.navItemHasBorder) {
        const border = `${this.navItemBorderSize} ${this.navItemBorderType} ${this.navItemBorderColor}`
        if (this.navItemBorderPosition.includes(0)) {
          style += `
              .tw-libsidenav-item > a {
                border-top: ${border};
              }
            `
        }

        if (this.navItemBorderPosition.includes(1)) {
          style += `
             .tw-libsidenav-item > a {
                border-bottom: ${border};
              }
            `
        }

        if (this.navItemBorderPosition.includes(2)) {
          style += `
              .tw-libsidenav-item > a {
                border-left: ${border};
              }
            `
        }

        if (this.navItemBorderPosition.includes(3)) {
          style += `
              .tw-libsidenav-item > a  {
                border-right: ${border};
              }
            `
        }
      }

      if (this.hasNavShadow) {
        style += `
          ::root.tw-libsidenav {
            box-shadow: 0 3px 6px rgba(204, 204, 204, 0.6);
          }
        `
      }

      if (this.hasNavTitltShadow) {
        style += `
          .tw-libsidenav-header {
            box-shadow: 0 3px 6px rgba(204, 204, 204, 0.6);
          }
        `
      }

      if (this.navTitleImg.length > 0) {
        style += `
          .tw-libsidenav-header {
            background: url('${this.$twApp.fileBaseUrl + this.navTitleImg[0].localPath}') no-repeat center;
            background-size:100% 100%;
          }
        `
      }

      if (this.subNavLineHeight) {
        style += `
         ::root .tw-libsidenav-item > a {
            line-height: ${this.subNavLineHeight};
          }
        `
      }

      if (this.subNavMaxHeight) {
        style += `
         ::root .tw-libsidenav-item .tw-libsidenav-menus {
            max-height: ${this.subNavMaxHeight};
          }
        `
      }

      this.addStyle(style)
    },

    init () {
      const roleIdList = this.$twApp.user.roleIdList || []
      const list = JSON.parse(JSON.stringify(this.dataIsFromPortal ? this.apiNavList : this.navs))
      const path = window.location.href
      const pathname = window.location.pathname
      const navList = []
      let activeNav = null
      const vm = this

      const fn = function (source, parent, level) {
        if (parent) {
          parent.children = []
        }

        source.forEach(item => {
          // 判断用户所在的机构类型是否有该导航的权限
          if ((!item.pageOrgTypes || item.pageOrgTypes.length === 0) || item.pageOrgTypes.includes(vm.$twApp.user.orgType)) {
            // 判断用户所在的角色是否有该导航的权限
            if ((!item.roles || item.roles.length === 0) || roleIdList.filter((role) => item.roles.includes(role)).length > 0) {
              item.parent = parent
              item.level = level

              if (item.activeText) {
                item.active = path.includes(item.activeText) || pathname.includes(item.href.replace(/^\./, ''))
              } else if (item.href) {
                item.active = pathname.includes(item.href.replace(/^\./, ''))
              }

              if (item.active) {
                activeNav = item
              }

              if (parent) {
              // 判断菜单显示回调函数是否显示
                if (typeof vm.navVifFunction === 'function') {
                  if (vm.navVifFunction(item, list)) {
                    parent.children.push(item)
                  }
                } else {
                  parent.children.push(item)
                }
              } else {
              // 判断菜单显示回调函数是否显示
                if (typeof vm.navVifFunction === 'function') {
                  if (vm.navVifFunction(item, list)) {
                    navList.push(item)
                  }
                } else {
                  navList.push(item)
                }
              }

              if (item.children) {
                item.expanded = false
                fn(item.children, item, level + 1)
              }
            }
          }
        })
      }

      fn(list, null, 0)

      this.navList = navList

      if (activeNav) {
        this.clickNav(activeNav)
      } else {
        this.activeNavById()
      }
    },

    activeNavById (id) {
      const vm = this
      let activeNav = null

      const fn = function (navs) {
        if (!activeNav) {
          for (const item of navs) {
            if (!activeNav) {
              if (id) {
                if (item.id === id || item.name === id) {
                  activeNav = item
                  return
                }
              } else {
                if (!item.children) {
                  activeNav = item
                  return
                }
              }

              if (!item.children) {
                activeNav = item
              }

              if (item.children) {
                fn(item.children)
              }
            }

            if (activeNav) {
              return vm.clickNav(activeNav)
            }
          }
        }
      }

      fn(this.navList)
      this.clickNav(activeNav)
    },

    collapseSameLevelNav (nav) {
      const parentNavs = nav.parent ? nav.parent.children : this.navList

      for (const item of parentNavs) {
        if (item !== nav) {
          item.expanded = false
        }
      }
    },

    clickNav (nav, event) {
      if (nav) {
        if (nav.children) {
          if (event) {
            event.preventDefault()
          }

          nav.expanded = !nav.expanded

          if (nav.expanded) {
            this.collapseSameLevelNav(nav)
          }
        }

        if (nav.parent) {
          let p = nav.parent

          do {
            delete p.active
            p.expanded = true
            this.collapseSameLevelNav(p)
            p = p.parent
          } while (p)
        }

        if (this.eventEnabel) {
          if (event) {
            event.preventDefault()
          }

          if (nav.children) {
            // noop
          } else {
            if (this.prevNav) {
              this.prevNav.active = false
            }

            nav.active = true

            this.prevNav = nav
          }

          this.activeNavId = nav.id || nav.name

          if (typeof this.clickNavFn === 'function') {
            this.clickNavFn(nav)
          }

          this.$emit('input', nav.pageId)
          this.$emit('update:activeNav', nav)
          this.$emit('change', nav.pageId)
        }
      }
    },

    computeNavIndentation (nav) {
      return parseInt(this.navPaddingX) + nav.level * parseInt(this.indentation) + 'px'
    }
  },

  created () {
    this.init()
  },

  watch: {
    value (val) {
      if (this.eventEnabel && this.activeNavId !== val) {
        this.activeNavById(val)
      }
    },

    navs: {
      deep: true,
      handler () {
        this.init()
      }
    },

    apiNavList () {
      this.init()
    }
  }
}
</script>

<style lang="scss">
@import './css/index.scss';
</style>
